<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue'
import type { FormInstance } from 'element-plus'
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue'
import { primaryColor_rgb } from '@/theme/config'

const formState = reactive<any>({})

const formRef = ref<FormInstance>()

const props = withDefaults(
	defineProps<{
		options: {
			type: 'select' | 'cascader' | 'tree' | 'time' | 'date' | 'date-range' | 'input' | 'number'
			id: string
			props: { label: string; [key: string]: any }
			innerComponentProps?: { options?: { label: string; value: string | number | boolean | object; disabled?: boolean }[]; [key: string]: any }
		}[]
		formProps?: { [key: string]: any }
		commitValidate?: boolean
	}>(),
	{
		formProps: () => ({}),
		commitValidate: false,
	}
)

const emits = defineEmits(['reset', 'search', 'collapsed'])

const config = reactive({
	// a-form默认props
	defaultFormProps: { labelWidth: '80px', labelPosition: 'left', size: 'default' },
	formItemStyle: { width: '90%' },
	formItemInnerElStyle: { width: '100%' },
	// 是否折叠
	isFold: true,
	// form高度
	formHeigh: '',
	// 表单占据的总行数
	rowNum: 1,
	// 表单单行的高度
	rowHeight: 0,
	//  折叠时展示的行数
	defaultRowNum: 1,
})

const transitionTime = 0.2
const transitionTimeStr = transitionTime + 's'

onMounted(() => {
	// console.log(formRef.value)
	config.rowNum = Math.ceil(props.options.length / 3)
	config.rowHeight = formRef.value!.$el.clientHeight / config.rowNum
	setFormHeigth(true)
})

function setFormHeigth(mounted = false) {
	if (config.isFold) {
		config.formHeigh = config.rowHeight * config.defaultRowNum + 'px'
		if (mounted) emits('collapsed', parseInt(config.formHeigh) + 10)
		else
			setTimeout(
				() => {
					emits('collapsed', parseInt(config.formHeigh) + 10)
				},
				transitionTime ? transitionTime * 1000 : 0
			)
	} else {
		config.formHeigh = config.rowHeight * config.rowNum + 'px'
		emits('collapsed', parseInt(config.formHeigh) + 10)
	}
	// 10是外边距高度
	// console.log(config.formHeigh)
}

function toggle() {
	config.isFold = !config.isFold
	setFormHeigth()
}

function bindReset() {
	formRef.value?.resetFields()
	emits('reset')
}
function bindSearch() {
	//console.log(config.form)
	if (props.commitValidate)
		formRef
			.value!.validate()
			.then((info: any) => {
				const data = toRaw(formState)
				Object.keys(data).forEach((k) => {
					if (data[k] === undefined || (Array.isArray(data[k]) && data[k].length == 0)) delete data[k]
				})
				emits('search', data)
			})
			.catch((err: any) => {
				console.log(err)
			})
	else {
		const data = toRaw(formState)
		Object.keys(data).forEach((k) => {
			if (data[k] === undefined || (Array.isArray(data[k]) && data[k].length == 0)) delete data[k]
		})
		emits('search', data)
	}
	if (props.options.length == 8) console.log(toRaw(formState))
}
function handleEnterSearch(e: KeyboardEvent) {
	if (e.key == 'Enter') bindSearch()
}
</script>

<template>
	<div class="searchFrom">
		<div class="form" :style="{ height: config.formHeigh }">
			<el-form :model="formState" ref="formRef" v-bind="{ ...config.defaultFormProps, ...props.formProps }" :hide-required-asterisk="!commitValidate">
				<el-row :gutter="20">
					<el-col :span="8" v-for="(item, index) in options" :key="index">
						<el-form-item v-if="item.type === 'select'" v-bind="item.props" :style="config.formItemStyle" :prop="item.id">
							<my-select v-model="formState[item.id]" v-bind="item.innerComponentProps" :placeholder="'请选择' + item.props.label" clearable :style="config.formItemInnerElStyle" />
						</el-form-item>

						<el-form-item :style="config.formItemStyle" v-if="item.type === 'cascader'" v-bind="item.props" :prop="item.id">
							<el-cascader
								v-bind="item.innerComponentProps"
								v-model="formState[item.id]"
								:placeholder="'请选择' + item.props.label"
								clearable
								:style="config.formItemInnerElStyle"
							/>
						</el-form-item>

						<el-form-item :style="config.formItemStyle" v-if="item.type === 'tree'" v-bind="item.props" :prop="item.id">
							<el-tree-select
								v-bind="item.innerComponentProps"
								v-model="formState[item.id]"
								:placeholder="'请选择' + item.props.label"
								clearable
								:style="config.formItemInnerElStyle"
							/>
						</el-form-item>

						<el-form-item :style="config.formItemStyle" v-if="item.type === 'time'" v-bind="item.props" :prop="item.id">
							<el-time-picker
								v-bind="item.innerComponentProps"
								v-model="formState[item.id]"
								clearable
								style="display: flex; width: 100%"
								:placeholder="'请选择' + item.props.label"
							/>
						</el-form-item>

						<el-form-item :style="config.formItemStyle" v-if="item.type === 'date'" v-bind="item.props" :prop="item.id">
							<el-date-picker
								v-bind="item.innerComponentProps"
								v-model="formState[item.id]"
								clearable
								style="display: flex; width: 100%"
								:placeholder="'请选择' + item.props.label"
							/>
						</el-form-item>

						<el-form-item :style="config.formItemStyle" v-if="item.type === 'date-range'" v-bind="item.props" :prop="item.id">
							<el-date-picker
								type="daterange"
								v-bind="item.innerComponentProps"
								v-model="formState[item.id]"
								style="width: 100%"
								start-placeholder="开始日期"
								end-placeholder="结束日期"
								range-separator="到"
								clearable
								:style="config.formItemInnerElStyle"
							/>
						</el-form-item>

						<el-form-item :style="config.formItemStyle" v-if="item.type === 'input'" v-bind="item.props" :prop="item.id">
							<el-input
								v-bind="item.innerComponentProps"
								v-model="formState[item.id]"
								:placeholder="'请输入' + item.props.label"
								clearable
								:style="config.formItemInnerElStyle"
								@keyup="handleEnterSearch"
							/>
						</el-form-item>

						<el-form-item :style="config.formItemStyle" v-if="item.type === 'number'" v-bind="item.props" :prop="item.id">
							<el-input-number
								v-bind="item.innerComponentProps"
								style="width: 100%"
								v-model="formState[item.id]"
								:placeholder="'请输入' + item.props.label"
								clearable
								:style="config.formItemInnerElStyle"
								@keyup="handleEnterSearch"
							/>
						</el-form-item>
					</el-col>
				</el-row>
			</el-form>
		</div>

		<div class="operate-wrap">
			<div class="operate">
				<el-button @click="bindReset" :size="config.defaultFormProps.size">{{ $t('global.reset') }}</el-button>
				<el-button type="primary" @click="bindSearch" :size="config.defaultFormProps.size" style="margin-left: 6px"> {{ $t('global.query') }} </el-button>
				<div style="margin-left: 8px; cursor: pointer; user-select: none; display: flex" @click="toggle" v-if="options.length > 3 * config.defaultRowNum">
					<span :style="{ color: primaryColor_rgb, fontSize: '14px' }">{{ config.isFold ? '展开' : '折叠' }}</span>
					<span>
						<el-icon v-show="config.isFold" :style="{ color: primaryColor_rgb }" size="18px"><ArrowDown /></el-icon>
						<el-icon v-show="!config.isFold" :style="{ color: primaryColor_rgb }" size="18px"><ArrowUp /></el-icon>
					</span>
				</div>
			</div>
		</div>
	</div>
</template>

<style scoped lang="scss">
.searchFrom {
	padding-top: 10px;
	display: flex;
	.form {
		width: calc(100% - 200px);
		overflow: hidden;
		transition: height v-bind(transitionTimeStr);

		:deep(.el-select__tags) {
			flex-wrap: nowrap;
		}
		:deep(.el-select .el-select__tags > span) {
			display: flex;
			flex-wrap: nowrap;
			overflow: hidden;
		}
		:deep(.el-form-item--default) {
			margin-bottom: 10px;
		}

		:deep(.el-form-item__label) {
			white-space: nowrap;
			overflow: hidden;
			text-overflow: ellipsis;
		}
	}

	.operate-wrap {
		width: 200px;
		.operate {
			display: flex;
			justify-content: flex-end;
			align-items: center;
		}
	}
}

@media print {
	.searchFrom .form {
		height: auto !important;
	}
}
</style>
